home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / umich / tex / tex29 / sttexsrc.zoo / src / mlst-hlst.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-03-13  |  25.9 KB  |  991 lines

  1.  
  2. /*
  3.  * @(#)mlst-hlst.c 2.6 EPA
  4.  *
  5.  * Copyright 1987,1988 Pat J Monardo
  6.  *
  7.  * Redistribution of this file is permitted through
  8.  * the specifications in the file COPYING.
  9.  *
  10.  * 
  11.  */
  12.  
  13. #include "tex.h"
  14. #include "scan.h"
  15. #include "box.h"
  16. #include "math.h"
  17. #include "pack.h"
  18. #include "tfm.h"
  19. #include "mlst-hlst.h"
  20.  
  21. qword   cur_c;
  22. fnt     cur_f;
  23. qqqq    cur_i;
  24. ptr     cur_mlist;
  25. scal    cur_mu;
  26. int     cur_size;
  27. int     cur_style;
  28. bool    mlist_penalties;
  29.  
  30. ptr
  31. clean_box (p, s)
  32.     ptr     p;
  33.     int     s;
  34. {
  35.     ptr     q;
  36.     ptr     r;
  37.     ptr     x;
  38.     int     save_style;
  39.  
  40.     switch (math_type(p))
  41.     {
  42.     case MATH_CHAR:
  43.         cur_mlist = new_noad();
  44.         mem[nucleus(cur_mlist)] = mem[p];
  45.         break;
  46.  
  47.     case SUB_BOX:
  48.         q = info(p);
  49.         goto found; 
  50.     
  51.     case SUB_MLIST:
  52.         cur_mlist = info(p);
  53.         break;
  54.     
  55.     default:
  56.         q = new_null_box();
  57.         goto found;
  58.     }
  59.     save_style = cur_style;
  60.     cur_style = s;
  61.     mlist_penalties = FALSE;
  62.     mlist_to_hlist();
  63.     q = link(temp_head);
  64.     cur_style = save_style;
  65.     change_size_and_mu();
  66.  
  67. found:
  68.     if (is_char_node(q) || q == NULL)
  69.         x = hpack(q, NATURAL);  
  70.     else if (link(q) == NULL &&
  71.             type(q) <= VLIST_NODE &&
  72.             shift_amount(q) == 0)
  73.             x = q;
  74.     else x = hpack(q, NATURAL);
  75.     q = list_ptr(x);
  76.     if (is_char_node(q)) {
  77.         r = link(q);
  78.         if (r != NULL &&
  79.             link(r) == NULL &&  
  80.             !is_char_node(r) &&
  81.             type(r) == KERN_NODE) {
  82.             free_node(r, SMALL_NODE_SIZE);
  83.             link(q) = NULL;
  84.         }
  85.     }
  86.     return x;
  87. }
  88.  
  89. fetch (a)
  90.     ptr     a;
  91. {
  92.     cur_c = character(a);
  93.     cur_f = fam_fnt(fam(a) + cur_size);
  94.     if (cur_f == null_font) {
  95.         print_err("");
  96.         print_size(cur_size);
  97.         print_char(' ');
  98.         print_int(fam(a));
  99.         print(" is undefined (character ");
  100.         print_ASCII(qo(cur_c));
  101.         print_char(')');
  102.         help_undefd_mathchar();
  103.         error();
  104.         cur_i = null_character;
  105.         math_type(a) = EMPTY;
  106.     } else {
  107.         if (qo(cur_c) >= font_bc[cur_f] &&
  108.             qo(cur_c) <= font_ec[cur_f])
  109.             cur_i = char_info(cur_f, cur_c);
  110.         else cur_i = null_character;
  111.         if (!char_exists(cur_i)) {
  112.             char_warning(cur_f, qo(cur_c));
  113.             math_type(a) = EMPTY;
  114.         }
  115.     }
  116. }
  117.  
  118. char    math_spacing[] = 
  119.         "0234000122*4000133**3**344*0400400*000000234000111*1111112341011";
  120.  
  121. #define choose_mlist(L) \
  122.     {p = L(q); L(q) = NULL;}
  123.  
  124. mlist_to_hlist ()
  125. {
  126.     ptr     p;
  127.     ptr     q;
  128.     ptr     r;
  129.     int     s;
  130.     int     t;
  131.     ptr     x;
  132.     ptr     y;
  133.     ptr     z;
  134.     val     pen;
  135.     scal    delta;
  136.     scal    max_d;
  137.     scal    max_h;
  138.     ptr     mlist;
  139.     int     style;
  140.     int     r_type;
  141.     bool    penalties;
  142.     int     save_style;
  143.  
  144.     mlist = cur_mlist;
  145.     penalties = mlist_penalties;
  146.     style = cur_style;
  147.     q = mlist;
  148.     r = NULL;
  149.     r_type = OP_NOAD;
  150.     max_h = 0;
  151.     max_d = 0;
  152.     change_size_and_mu();
  153.  
  154.     while (q != NULL)
  155.     {
  156. reswitch:
  157.         delta = 0;
  158.         switch (type(q))
  159.         {
  160.         case BIN_NOAD:  
  161.             switch (r_type)
  162.             {
  163.             case BIN_NOAD:
  164.             case OP_NOAD:
  165.             case REL_NOAD:
  166.             case OPEN_NOAD:
  167.             case PUNCT_NOAD:
  168.             case LEFT_NOAD:
  169.                 type(q) = ORD_NOAD;
  170.                 goto reswitch;
  171.  
  172.             default:
  173.                 break;
  174.             }
  175.             break;
  176.  
  177.         case REL_NOAD:
  178.         case CLOSE_NOAD:
  179.         case PUNCT_NOAD:
  180.         case RIGHT_NOAD:
  181.             if (r_type == BIN_NOAD)
  182.                 type(r) = ORD_NOAD;
  183.             if (type(q) == RIGHT_NOAD)
  184.                 goto done_with_noad;
  185.             break;
  186.  
  187.         case LEFT_NOAD:
  188.             goto done_with_noad;
  189.  
  190.         case FRACTION_NOAD:
  191.             make_fraction(q);
  192.             goto check_dimensions;
  193.         
  194.         case OP_NOAD:
  195.             delta = make_op(q);
  196.             if (subtype(q) == LIMITS)
  197.                 goto check_dimensions;
  198.             break;
  199.  
  200.         case ORD_NOAD:
  201.             make_ord(q);
  202.             break;
  203.  
  204.         case OPEN_NOAD:
  205.         case INNER_NOAD:
  206.             break;
  207.         
  208.         case RADICAL_NOAD:
  209.             make_radical(q);
  210.             break;
  211.         
  212.         case OVER_NOAD:
  213.             make_over(q);
  214.             break;
  215.  
  216.         case UNDER_NOAD:
  217.             make_under(q);
  218.             break;
  219.     
  220.         case ACCENT_NOAD:
  221.             make_math_accent(q);
  222.             break;
  223.         
  224.         case VCENTER_NOAD:
  225.             make_vcenter(q);
  226.             break;
  227.         
  228.         case STYLE_NODE:
  229.             cur_style = subtype(q);
  230.             change_size_and_mu();
  231.             goto done_with_node;
  232.         
  233.         case CHOICE_NODE:
  234.             switch (cur_style>>1)
  235.             {
  236.             case 0: choose_mlist(display_mlist); break;
  237.             case 1: choose_mlist(text_mlist); break;
  238.             case 2: choose_mlist(script_mlist); break;
  239.             case 3: choose_mlist(script_script_mlist); break;
  240.             }
  241.             flush_node_list(display_mlist(q));
  242.             flush_node_list(text_mlist(q));
  243.             flush_node_list(script_mlist(q));
  244.             flush_node_list(script_script_mlist(q));
  245.             type(q) = STYLE_NODE;
  246.             subtype(q) = cur_style;
  247.             width(q) = 0;
  248.             depth(q) = 0;
  249.             if (p != NULL) {
  250.                 z = link(q);
  251.                 link(q) = p;
  252.                 while (link(p) != NULL)
  253.                     p = link(p);
  254.                 link(p) = z;
  255.             }
  256.             goto done_with_node;
  257.  
  258.         case INS_NODE:
  259.         case MARK_NODE:
  260.         case ADJUST_NODE:
  261.         case WHATSIT_NODE:
  262.         case PENALTY_NODE:
  263.         case DISC_NODE:
  264.             goto done_with_node;
  265.         
  266.         case RULE_NODE:
  267.             if (height(q) > max_h)
  268.                 max_h = height(q);
  269.             if (depth(q) > max_d)
  270.                 max_d = depth(q);
  271.             goto done_with_node;
  272.  
  273.         case GLUE_NODE:
  274.             if (subtype(q) == MU_GLUE) {
  275.                 x = glue_ptr(q);
  276.                 y = math_glue(x, cur_mu);
  277.                 delete_glue_ref(x);
  278.                 glue_ptr(q) = y;
  279.                 subtype(q) = NORMAL;
  280.             } else if (cur_size != TEXT_SIZE &&
  281.                 subtype(q) == COND_MATH_GLUE) {
  282.                 p = link(q);
  283.                 if (p != NULL &&
  284.                     (type(p) == GLUE_NODE ||
  285.                     type(p) == KERN_NODE)) {
  286.                     link(q) = link(p);
  287.                     link(p) = NULL;
  288.                     flush_node_list(p);
  289.                 }
  290.             }
  291.             goto done_with_node;
  292.         
  293.         case KERN_NODE:
  294.             math_kern(q, cur_mu);
  295.             goto done_with_node;
  296.         
  297.         default:
  298.             confusion("mlist1");
  299.         }
  300.  
  301.         switch (math_type(nucleus(q)))
  302.         {
  303.         case MATH_CHAR:
  304.         case MATH_TEXT_CHAR:
  305.             fetch(nucleus(q));
  306.             if (char_exists(cur_i)) {
  307.                 delta = char_italic(cur_f, cur_i);
  308.                 p = new_character(cur_f, qo(cur_c));
  309.                 if (math_type(nucleus(q)) == MATH_TEXT_CHAR &&
  310.                     space(cur_f) != 0)
  311.                     delta = 0;
  312.                 if (math_type(subscr(q)) == EMPTY && delta != 0) {
  313.                     link(p) = new_kern(delta);
  314.                     delta = 0;
  315.                 }
  316.             } else
  317.                 p = NULL;
  318.             break;
  319.         
  320.         case EMPTY:
  321.             p = NULL;
  322.             break;
  323.  
  324.         case SUB_BOX:
  325.             p = info(nucleus(q));
  326.             break;
  327.  
  328.         case SUB_MLIST:
  329.             cur_mlist = info(nucleus(q));
  330.             save_style = cur_style;
  331.             mlist_penalties = FALSE;
  332.             mlist_to_hlist();
  333.             cur_style = save_style;
  334.             change_size_and_mu();
  335.             p = hpack(link(temp_head), NATURAL); 
  336.             break;
  337.  
  338.         default:
  339.             confusion("mlist2");
  340.         }
  341.         new_hlist(q) = p;
  342.         if (math_type(subscr(q)) == EMPTY && 
  343.             math_type(supscr(q)) == EMPTY)
  344.             goto check_dimensions;
  345.         make_scripts(q, delta);
  346.         
  347. check_dimensions:
  348.         z = hpack((ptr)new_hlist(q), NATURAL);
  349.         if (height(z) > max_h)
  350.             max_h = height(z);
  351.         if (depth(z) > max_d)
  352.             max_d = depth(z);
  353.         free_node(z, BOX_NODE_SIZE);
  354.  
  355. done_with_noad:
  356.         r = q;
  357.         r_type = type(r);
  358.  
  359. done_with_node:
  360.         q = link(q);
  361.     } 
  362.  
  363.     if (r_type == BIN_NOAD)
  364.         type(r) = ORD_NOAD;
  365.     p = temp_head;
  366.     link(p) = NULL;
  367.     q = mlist;
  368.     r_type = 0;
  369.     cur_style = style;
  370.     change_size_and_mu();
  371.  
  372.     while (q != NULL) {
  373.         t = ORD_NOAD;
  374.         s = NOAD_SIZE;
  375.         pen = INF_PENALTY;
  376.         switch (type(q))
  377.         {
  378.         case OP_NOAD:
  379.         case OPEN_NOAD:
  380.         case CLOSE_NOAD:
  381.         case PUNCT_NOAD:
  382.         case INNER_NOAD:
  383.             t = type(q);
  384.             break;
  385.         
  386.         case BIN_NOAD:
  387.             t = BIN_NOAD;
  388.             pen = bin_op_penalty;
  389.             break;
  390.         
  391.         case REL_NOAD:
  392.             t = REL_NOAD;
  393.             pen = rel_penalty;
  394.             break; 
  395.         
  396.         case ORD_NOAD:
  397.         case VCENTER_NOAD:
  398.         case OVER_NOAD:
  399.         case UNDER_NOAD:
  400.             break;
  401.  
  402.         case RADICAL_NOAD:
  403.             s = RADICAL_NOAD_SIZE;
  404.             break;
  405.  
  406.         case ACCENT_NOAD:
  407.             s = ACCENT_NOAD_SIZE;
  408.             break;
  409.  
  410.         case FRACTION_NOAD:
  411.             t = INNER_NOAD;
  412.             s = FRACTION_NOAD_SIZE;
  413.             break;
  414.  
  415.         case LEFT_NOAD:
  416.         case RIGHT_NOAD:
  417.             t = make_left_right(q, style, max_d, max_h);
  418.             break;
  419.         
  420.         case STYLE_NODE:
  421.             cur_style = subtype(q);
  422.             s = STYLE_NODE_SIZE;
  423.             change_size_and_mu();
  424.             goto delete_q;
  425.             break;
  426.  
  427.         case WHATSIT_NODE:
  428.         case PENALTY_NODE:
  429.         case RULE_NODE:
  430.         case DISC_NODE:
  431.         case ADJUST_NODE:
  432.         case INS_NODE:
  433.         case MARK_NODE:
  434.         case GLUE_NODE:
  435.         case KERN_NODE:
  436.             link(p) = q;
  437.             p = q;
  438.             q = link(q);
  439.             link(p) = NULL;
  440.             continue;
  441.         
  442.         default:
  443.             confusion("mlist3");
  444.         }
  445.  
  446.         if (r_type > 0) {
  447.             switch (math_spacing[r_type * 8 + t + magic_offset]) 
  448.             {
  449.             case '0':
  450.                 x = 0;
  451.                 break;
  452.  
  453.             case '1':
  454.                 if (cur_style < SCRIPT_STYLE)
  455.                     x = THIN_MU_SKIP_CODE;
  456.                 else x = 0;
  457.                 break;
  458.  
  459.             case '2':
  460.                 x = THIN_MU_SKIP_CODE;
  461.                 break;
  462.  
  463.             case '3':
  464.                 if (cur_style < SCRIPT_STYLE)
  465.                     x = MED_MU_SKIP_CODE;
  466.                 else x = 0;
  467.                 break;
  468.  
  469.             case '4':
  470.                 if (cur_style < SCRIPT_STYLE)
  471.                     x = THICK_MU_SKIP_CODE;
  472.                 else x = 0;
  473.                 break;
  474.  
  475.             default:
  476.                 confusion("mlist4");
  477.                 break;
  478.             }
  479.             if (x != 0) {
  480.                 y = math_glue(glue_par(x), cur_mu);
  481.                 z = new_glue(y);
  482.                 glue_ref_count(y) = NULL;
  483.                 link(p) = z;
  484.                 p = z;
  485.                 subtype(z) = x + 1;
  486.             }
  487.         }
  488.         if (new_hlist(q) != NULL) {
  489.             link(p) = new_hlist(q);
  490.             do p = link(p);
  491.             while (link(p) != NULL);
  492.         }
  493.         if (penalties && link(q) != NULL && pen < INF_PENALTY) {
  494.             r_type = type(link(q));
  495.             if (r_type != PENALTY_NODE && r_type != REL_NOAD) {
  496.                 z = new_penalty(pen);
  497.                 link(p) = z;
  498.                 p = z;
  499.             }
  500.         }
  501.         r_type = t;
  502.  
  503. delete_q:
  504.         r = q;
  505.         q = link(q);
  506.         free_node(r, s);
  507.     }
  508. }
  509.  
  510. make_over (q)
  511.     ptr q;
  512. {
  513.     info(nucleus(q)) =
  514.         overbar(clean_box(nucleus(q), cramped_style(cur_style)),
  515.                 3 * default_rule_thickness, default_rule_thickness);
  516.     math_type(nucleus(q)) = SUB_BOX;
  517. }
  518.  
  519. make_under (q)
  520.     ptr     q;
  521. {
  522.     ptr     p;
  523.     ptr     x;
  524.     ptr     y;
  525.     scal    delta;
  526.  
  527.     x = clean_box(nucleus(q), cur_style);
  528.     p = new_kern(3 * default_rule_thickness);
  529.     link(x) = p;
  530.     link(p) = fraction_rule(default_rule_thickness);
  531.     y = vpack(x, NATURAL);
  532.     delta = height(y) + depth(y) + default_rule_thickness;
  533.     height(y) = height(x);
  534.     depth(y) = delta - height(y);
  535.     info(nucleus(q)) = y;
  536.     math_type(nucleus(q)) = SUB_BOX;
  537. }
  538.  
  539. make_vcenter (q)
  540.     ptr     q;
  541. {
  542.     ptr     v;
  543.     scal    delta;
  544.  
  545.     v = info(nucleus(q));
  546.     if (type(v) != VLIST_NODE)
  547.         confusion("vcenter");
  548.     delta = height(v) + depth(v);
  549.     height(v) = axis_height(cur_size) + half(delta);
  550.     depth(v) = delta - height(v);
  551. }
  552.  
  553. make_radical (q)
  554.     ptr     q;
  555. {
  556.     ptr     x;
  557.     ptr     y;
  558.     scal    clr;
  559.     scal    delta;
  560.  
  561.     x = clean_box(nucleus(q), cramped_style(cur_style));
  562.     if (cur_style < TEXT_STYLE)
  563.         clr = default_rule_thickness + (abs(math_x_height(cur_size))>>2);
  564.     else {
  565.         clr = default_rule_thickness;
  566.         clr += (abs(clr)>>2);
  567.     }
  568.     y = var_delimiter(left_delimiter(q), cur_size,
  569.                         height(x) + depth(x) + clr + default_rule_thickness);
  570.     delta = depth(y) - (height(x) + depth(x) + clr);
  571.     if (delta > 0) clr += half(delta);
  572.     shift_amount(y) = -(height(x) + clr);
  573.     link(y)  = overbar(x, clr, height(y));
  574.     info(nucleus(q)) = hpack(y, NATURAL);
  575.     math_type(nucleus(q)) = SUB_BOX;
  576. }
  577.  
  578. make_math_accent (q)
  579.     ptr     q;
  580. {
  581.     int     a;
  582.     qword   c;
  583.     fnt     f;
  584.     scal    h;
  585.     qqqq    i;
  586.     ptr     p;
  587.     scal    s;
  588.     scal    w;
  589.     ptr     x;
  590.     ptr     y;
  591.     scal    delta;
  592.  
  593.     fetch(accent_chr(q)); 
  594.     if (char_exists(cur_i)) {
  595.         i = cur_i;
  596.         c = cur_c;
  597.         f = cur_f;
  598.         s = 0;
  599.         if (math_type(nucleus(q)) == MATH_CHAR) {
  600.             fetch(nucleus(q));
  601.             if (char_tag(cur_i) == LIG_TAG) {
  602.                 a = lig_kern_start(cur_f, cur_i);
  603.                 do  {
  604.                     cur_i = font_info[a].qqqq;
  605.                     if (qo(next_char(cur_i)) == skew_char[cur_f]) {
  606.                         if (op_bit(cur_i) >= KERN_FLAG)
  607.                             s = char_kern(cur_f, cur_i);
  608.                         break;
  609.                     }
  610.                     incr(a);
  611.                 } while (stop_bit(cur_i) < STOP_FLAG);
  612.             }
  613.         }
  614.         x = clean_box(nucleus(q), cramped_style(cur_style));
  615.         w = width(x);
  616.         h = height(x);
  617.         loop {
  618.             if (char_tag(i) != LIST_TAG)
  619.                 break;
  620.             y = rem_byte(i);
  621.             i = char_info(f, y);
  622.             if (char_width(f, i) > w)
  623.                 break;
  624.             c = y;
  625.         }
  626.         delta = (h < x_height(f) ? h : x_height(f));
  627.         if ((math_type(supscr(q)) != EMPTY ||
  628.             math_type(subscr(q)) != EMPTY) &&
  629.             math_type(nucleus(q)) == MATH_CHAR) {
  630.                 flush_node_list(x);
  631.                 x = new_noad(); 
  632.                 mem[nucleus(x)] = mem[nucleus(q)];
  633.                 mem[supscr(x)] = mem[supscr(q)];
  634.                 mem[subscr(x)] = mem[subscr(q)];
  635.                 mem[supscr(q)].hh = empty_field;
  636.                 mem[subscr(q)].hh = empty_field;
  637.                 math_type(nucleus(q)) = SUB_MLIST;
  638.                 info(nucleus(q)) = x;
  639.                 x = clean_box(nucleus(q), cur_style);
  640.                 delta = delta + height(x) - h;
  641.                 h = height(x);
  642.         }
  643.         y = char_box(f, c);
  644.         shift_amount(y) = s + half(w - width(y));
  645.         width(y) = 0;
  646.         p = new_kern(-delta);
  647.         link(p) = x;
  648.         link(y) = p;
  649.         y = vpack(y, NATURAL);
  650.         width(y) = width(x);
  651.         if (height(y) < h) {
  652.             p = new_kern(h - height(y));
  653.             link(p) = list_ptr(y);
  654.             list_ptr(y) = p;
  655.             height(y) = h;
  656.         }
  657.         info(nucleus(q)) = y;
  658.         math_type(nucleus(q)) = SUB_BOX;
  659.     }
  660. }
  661.  
  662. make_fraction (q)
  663.     ptr     q;
  664. {
  665.     ptr     p;
  666.     ptr     v;
  667.     ptr     x;
  668.     ptr     y;
  669.     ptr     z;
  670.     scal    clr;
  671.     scal    delta;
  672.     scal    delta1;
  673.     scal    delta2;
  674.     scal    shift_up;
  675.     scal    shift_down;
  676.  
  677.     if (thickness(q) == DEFAULT_CODE)
  678.         thickness(q) = default_rule_thickness;
  679.     x = clean_box(numerator(q), num_style(cur_style));
  680.     z = clean_box(denominator(q), denom_style(cur_style));
  681.     if (width(x) < width(z))
  682.         x = rebox(x, width(z));
  683.     else z = rebox(z, width(x));
  684.     if (cur_style < TEXT_STYLE) {
  685.         shift_up = num1(cur_size);
  686.         shift_down = denom1(cur_size);
  687.     } else {
  688.         shift_down = denom2(cur_size);
  689.         if (thickness(q) != 0)
  690.             shift_up = num2(cur_size);
  691.         else shift_up = num3(cur_size);
  692.     }
  693.     if (thickness(q) == 0) {
  694.         if (cur_style < TEXT_STYLE)
  695.             clr = 7 * default_rule_thickness;
  696.         else clr = 3 * default_rule_thickness;
  697.         delta = half(clr - ((shift_up - depth(x)) - (height(z) - shift_down)));
  698.         if (delta > 0) {
  699.             shift_up += delta;
  700.             shift_down += delta;
  701.         }
  702.     } else {
  703.         if (cur_style < TEXT_STYLE)
  704.             clr = 3 * thickness(q);
  705.         else clr = thickness(q);
  706.         delta = half(thickness(q));
  707.         delta1 = clr -
  708.             ((shift_up - depth(x)) - (axis_height(cur_size) + delta));
  709.         delta2 = clr - 
  710.             ((axis_height(cur_size) - delta) - (height(z) - shift_down));
  711.         if (delta1 > 0) shift_up += delta1;
  712.         if (delta2 > 0) shift_down += delta2;
  713.     }
  714.     v = new_null_box();
  715.     type(v) = VLIST_NODE;
  716.     height(v) = shift_up + height(x);
  717.     depth(v) = depth(z) + shift_down;
  718.     width(v) = width(x);
  719.     if (thickness(q) == 0) {
  720.         p = new_kern((shift_up - depth(x)) - (height(z) - shift_down));
  721.         link(p) = z;
  722.     } else {
  723.         y = fraction_rule(thickness(q));
  724.         p = new_kern((axis_height(cur_size)-delta) - (height(z)-shift_down));
  725.         link(y) = p;
  726.         link(p) = z;
  727.         p = new_kern((shift_up - depth(x)) - (axis_height(cur_size) + delta));
  728.         link(p)  = y;
  729.     }
  730.     link(x) = p;
  731.     list_ptr(v) = x;
  732.     if (cur_style < TEXT_STYLE)
  733.         delta = delim1(cur_size);
  734.     else delta = delim2(cur_size);
  735.     x = var_delimiter(left_delimiter(q), cur_size, delta);
  736.     link(x) = v;
  737.     z = var_delimiter(right_delimiter(q), cur_size, delta);
  738.     link(v) = z;
  739.     new_hlist(q) = hpack(x, NATURAL);
  740. }
  741.  
  742. scal
  743. make_op (q)
  744.     ptr     q;
  745. {
  746.     ptr     p;
  747.     ptr     v;
  748.     ptr     x;
  749.     ptr     y;
  750.     ptr     z;
  751.     scal    delta;
  752.     scal    shift_up;
  753.     scal    shift_down;
  754.  
  755.     if (subtype(q) == NORMAL && cur_style < TEXT_STYLE)
  756.         subtype(q) = LIMITS;
  757.     if (math_type(nucleus(q)) == MATH_CHAR) {
  758.         fetch(nucleus(q));
  759.         if (cur_style < TEXT_STYLE && char_tag(cur_i) == LIST_TAG) {
  760.             cur_c = rem_byte(cur_i);
  761.             character(nucleus(q)) = cur_c;
  762.             cur_i = char_info(cur_f, cur_c);
  763.         }
  764.         delta = char_italic(cur_f, cur_i);
  765.         x = clean_box(nucleus(q), cur_style);
  766.         if (math_type(subscr(q)) != EMPTY && subtype(q) != LIMITS)
  767.             width(x) -= delta;
  768.         shift_amount(x) = half(height(x) - depth(x)) - axis_height(cur_size);
  769.         math_type(nucleus(q)) = SUB_BOX;
  770.         info(nucleus(q)) = x;
  771.     } else delta = 0;
  772.     if (subtype(q) == LIMITS) {
  773.         x = clean_box(supscr(q), sup_style(cur_style));
  774.         y = clean_box(nucleus(q), cur_style);
  775.         z = clean_box(subscr(q), sub_style(cur_style));
  776.         v = new_null_box();
  777.         type(v) = VLIST_NODE;
  778.         width(v) = width(y);
  779.         if (width(x) > width(v))
  780.             width(v) = width(x);
  781.         if (width(z) > width(v))
  782.             width(v) = width(z);
  783.         x = rebox(x, width(v));
  784.         y = rebox(y, width(v));
  785.         z = rebox(z, width(v));
  786.         shift_amount(x) = half(delta);
  787.         shift_amount(z) = -shift_amount(x);
  788.         height(v) = height(y);
  789.         depth(v) = depth(y);
  790.         if (math_type(supscr(q)) == EMPTY) {
  791.             free_node(x, BOX_NODE_SIZE);
  792.             list_ptr(v) = y;
  793.         } else {
  794.             shift_up = big_op_spacing3 - depth(x);
  795.             if (shift_up < big_op_spacing1)
  796.                 shift_up = big_op_spacing1;
  797.             p = new_kern(shift_up);
  798.             link(p) = y;
  799.             link(x) = p;
  800.             p = new_kern(big_op_spacing5);
  801.             link(p) = x;
  802.             list_ptr(v) = p;
  803.             height(v) += big_op_spacing5 + height(x) + depth(x) + shift_up;
  804.         }
  805.         if (math_type(subscr(q)) == EMPTY) {
  806.             free_node(z, BOX_NODE_SIZE);
  807.         } else {
  808.             shift_down = big_op_spacing4 - height(z);
  809.             if (shift_down < big_op_spacing2)
  810.                 shift_down = big_op_spacing2;
  811.             p = new_kern(shift_down);
  812.             link(y) = p;
  813.             link(p) = z;
  814.             p = new_kern(big_op_spacing5);
  815.             link(z) = p;
  816.             depth(v) += big_op_spacing5 + height(z) + depth(z) + shift_down;
  817.         }
  818.         new_hlist(q) = v;
  819.     }
  820.     return delta;
  821. }
  822.  
  823. make_ord (q)
  824.     ptr     q;
  825. {
  826.     int     a;
  827.     ptr     p;
  828.  
  829. restart:
  830.     if (math_type(subscr(q)) == EMPTY &&
  831.         math_type(supscr(q)) == EMPTY &&
  832.         math_type(nucleus(q)) == MATH_CHAR) {
  833.         p = link(q);
  834.         if (p != NULL &&
  835.             type(p) >= ORD_NOAD &&
  836.             type(p) <= PUNCT_NOAD &&
  837.             math_type(nucleus(p)) == MATH_CHAR &&
  838.             fam(nucleus(p)) == fam(nucleus(q))) {
  839.             math_type(nucleus(q)) = MATH_TEXT_CHAR;
  840.             fetch(nucleus(q));
  841.             if (char_tag(cur_i) == LIG_TAG) {
  842.                 a = lig_kern_start(cur_f, cur_i);
  843.                 cur_c = character(nucleus(p));
  844.                 do  {
  845.                     cur_i = font_info[a].qqqq;
  846.                     if (next_char(cur_i) == cur_c) {
  847.                         if (op_bit(cur_i) >= KERN_FLAG) {
  848.                             p = new_kern(char_kern(cur_f, cur_i));
  849.                             link(p) = link(q);
  850.                             link(q) = p;
  851.                             return;
  852.                         } else {
  853.                             link(q) = link(p);
  854.                             math_type(nucleus(q)) = MATH_CHAR;
  855.                             character(nucleus(q)) = rem_byte(cur_i);
  856.                             mem[subscr(q)] = mem[subscr(p)];
  857.                             mem[supscr(q)] = mem[supscr(p)];
  858.                             free_node(p, NOAD_SIZE);
  859.                             goto restart;
  860.                         }
  861.                     }
  862.                     incr(a);
  863.                 } while (stop_bit(cur_i) < STOP_FLAG);
  864.             }
  865.         }
  866.     }
  867. }
  868.  
  869. make_scripts (q, delta)
  870.     ptr     q;
  871.     scal    delta;
  872. {
  873.     ptr     p;
  874.     int     t;
  875.     ptr     x;
  876.     ptr     y;
  877.     ptr     z;
  878.     scal    clr;
  879.     scal    shift_up;
  880.     scal    shift_down;
  881.  
  882.     p = new_hlist(q);
  883.     if (is_char_node(p)) {
  884.         shift_up = 0;
  885.         shift_down = 0;
  886.     } else {
  887.         z = hpack(p, NATURAL);
  888.         if (cur_style < SCRIPT_STYLE)   
  889.             t = SCRIPT_SIZE;
  890.         else t = SCRIPT_SCRIPT_SIZE;
  891.         shift_up = height(z) - sup_drop(t);
  892.         shift_down = depth(z) + sub_drop(t);
  893.         free_node(z, BOX_NODE_SIZE);
  894.     }
  895.     if (math_type(supscr(q)) == EMPTY) {
  896.         x = clean_box(subscr(q), sub_style(cur_style));
  897.         width(x) += script_space;
  898.         if (shift_down < sub1(cur_size))
  899.             shift_down = sub1(cur_size);
  900.         clr = height(x) - (abs(math_x_height(cur_size) * 4) / 5);
  901.         if (shift_down < clr)
  902.             shift_down = clr;
  903.         shift_amount(x) = shift_down;
  904.     } else {
  905.         x = clean_box(supscr(q), sup_style(cur_style));
  906.         width(x) += script_space;
  907.         if (odd(cur_style))
  908.             clr = sup3(cur_size);
  909.         else if (cur_style < TEXT_STYLE)
  910.             clr = sup1(cur_size);
  911.         else clr = sup2(cur_size);
  912.         if (shift_up < clr)
  913.             shift_up = clr;
  914.         clr = depth(x) + (abs(math_x_height(cur_size))>>2);
  915.         if (shift_up < clr)
  916.             shift_up = clr;
  917.         if (math_type(subscr(q)) == EMPTY) {
  918.             shift_amount(x) = -shift_up;
  919.         } else {
  920.             y = clean_box(subscr(q), sub_style(cur_style));
  921.             width(y) += script_space;
  922.             if (shift_down < sub2(cur_size))
  923.                 shift_down = sub2(cur_size);
  924.             clr = 4 * default_rule_thickness -
  925.                         ((shift_up - depth(x)) - (height(y) - shift_down));
  926.             if (clr > 0) {
  927.                 shift_down += clr;
  928.                 clr = (abs(math_x_height(cur_size) * 4) / 5) -
  929.                         (shift_up - depth(x));
  930.                 if (clr > 0) {
  931.                     shift_up += clr;
  932.                     shift_down -= clr;
  933.                 }
  934.             }
  935.             shift_amount(x) = delta;
  936.             p = new_kern((shift_up - depth(x)) - (height(y) - shift_down));
  937.             link(x) = p;
  938.             link(p) = y;
  939.             x = vpack(x, NATURAL);
  940.             shift_amount(x) = shift_down;
  941.         }
  942.     }
  943.     if (new_hlist(q) == NULL) {
  944.         new_hlist(q) = x;
  945.     } else {
  946.         p = new_hlist(q);
  947.         while (link(p) != NULL)
  948.             p = link(p);
  949.         link(p) = x;
  950.     }
  951. }
  952.  
  953. make_left_right (q, style, max_d, max_h)
  954.     ptr     q;
  955.     int     style;
  956.     scal    max_d;
  957.     scal    max_h;
  958. {
  959.     scal    delta;
  960.     scal    delta1;
  961.     scal    delta2;
  962.  
  963.     if (style  < SCRIPT_STYLE)
  964.         cur_size = TEXT_SIZE;
  965.     else cur_size = 16 * ((style - TEXT_STYLE)>>1);
  966.     delta2 = max_d + axis_height(cur_size);
  967.     delta1 = max_h + max_d - delta2;
  968.     if (delta2 > delta1)
  969.         delta1 = delta2;
  970.     delta = (delta1 / 500) * delimiter_factor;
  971.     delta2 = delta1 + delta1 - delimiter_shortfall;
  972.     if (delta < delta2)
  973.         delta = delta2;
  974.     new_hlist(q) = var_delimiter(delimiter(q), cur_size, delta);
  975.     return (type(q) - (LEFT_NOAD - OPEN_NOAD));
  976. }
  977.  
  978. int     magic_offset = - 9 * ORD_NOAD;
  979.  
  980. /*
  981.  *  Help text
  982.  */
  983.  
  984. help_undefd_mathchar ()
  985. {
  986.     help4("Somewhere in the math formula just ended, you used the",
  987.     "stated character from an undefined font family. For example,",
  988.     "plain TeX doesn't allow \\it or \\sl in subscripts. Proceed,",
  989.     "and I'll try to forget that I needed that character.");
  990. }
  991.